package	{
	import	flash.display.*;
	import flash.net.URLRequest;
	import flash.net.URLLoader;
	import flash.net.URLLoaderDataFormat;
	import	flash.events.*;
	import flash.display.Stage;
import flash.display.StageDisplayState;

	import	logica.*;
	import	com.jalheart.utils.Punto3D;
	import	com.jalheart.utils.Busquedas;
	public	class	mahjongg	extends	MovieClip{
		private	const	MARGEN_IZQUIERDO	:	uint	=	30;
		private	const	MARGEN_SUPERIOR		:	uint	=	30;

		private	var	_anchoFicha		:	uint	=	50;
		private	var	_altoFicha			:	uint	=	_anchoFicha*1.5;
		
		private	var	miCargador	:	URLLoader	=	new	URLLoader();
		private	var	configXML		:	XML;
		private	var	mapasXML		:	XML;
		private	var	mapaActXML	:	XML;
		private	var	mapaMatriz	:	Array;
		
		private	var	_misFichas		:	Array	=	new	Array();
		private	var	_cargadores	:	Array	=	new	Array();
		private	var	_misValores	:	Array	=	new	Array();
		
		private	var	_totalCargados	:	uint	=	0;
		private	var	_cargandoTodas	:	Boolean	=	false;
		
		private	var	_fichaActual		:	Ficha	=	null;
		private	var	_mapa				:	Mapa;
		public	function	mahjongg()
		{
			stage.displayState = StageDisplayState.FULL_SCREEN;
			miCargador.dataFormat			= URLLoaderDataFormat.TEXT;
			miCargador.addEventListener(Event.COMPLETE,alCargarSetsXML);
			iniciar("./cfg_sets.xml","./cfg_maps.xml");
			var	miaar:Array=new Array();
			miCronometro.controlador.iniciar();
		}
		public		function	iniciar(setsXML:String,mapsXML:String):void
		{
			miCargador.load(new URLRequest(setsXML));
			
			var	cargadorMapa	:	URLLoader	=	new	URLLoader();
			cargadorMapa.dataFormat	=	URLLoaderDataFormat.TEXT;
			cargadorMapa.addEventListener(Event.COMPLETE,alCargarMapaXML);
			cargadorMapa.load(new URLRequest(mapsXML));
		}
		private	function	alCargarSetsXML(e:Event):void
		{
			configXML	=	XML(e.target.data);
			configXML.ignoreWhitespace	=	true;
			cargarSet(configXML.set[0]);
		}
		private	function	alCargarMapaXML(e:Event):void
		{
			var	i	:	uint;
			var	j	:	uint;
			var	k	:	uint;
			mapasXML		=	XML(e.target.data);
			mapaActXML	=	mapasXML.mapa[0];
			/**/
			_mapa	=	new	Mapa(mapaActXML);
			/**/
			mapaActXML.ignoreWhitespace	=	true;
			mapaMatriz	=	new	Array(int(mapaActXML.@pisos));
			for(i=0;i<mapaMatriz.length;i++)
			{
				mapaMatriz[i]	=	new	Array(int(mapaActXML.@filas));
				for(j=0;j<mapaMatriz[i].length;j++)
				{
					mapaMatriz[i][j]	=	new	Array(int(mapaActXML.@columnas));
				}
			}
			for(i=0;i<mapaMatriz.length;i++)
				for(j=0;j<mapaMatriz[i].length;j++)
					for(k=0;k<mapaMatriz[i][j].length;k++)
						mapaMatriz[i][j][k]	=	null;
		}
		private	function	cargarSet(cual:XML):void
		{
			_totalCargados	=	0;
			_cargandoTodas	=	false;
			for(var i:uint=0;i<cual.ficha.length();i++)
			{
				for(var j:uint=0;j<cual.ficha[i].@repeticiones;j++)
				{
					_misFichas.push(new Ficha());
					(_misFichas[_misFichas.length-1] as Ficha).valor	=	cual.ficha[i].@valor;
					(_misFichas[_misFichas.length-1] as Ficha).addEventListener("click",alClickFicha);
					
					_cargadores.push(new	Loader());
					_cargadores[_cargadores.length-1].load(new URLRequest(cual.ficha[i].@img));
					_cargadores[_cargadores.length-1].contentLoaderInfo.addEventListener(Event.COMPLETE,alCargarImgFicha);
				}
			}
			_cargandoTodas	=	true;
		}
		private	function	alCargarImgFicha(e:Event):void
		{
			var	pos	:	uint	=	_cargadores.indexOf(e.target.loader);
			_misFichas[pos].imagen	=	e.target.content;
			_totalCargados++;
			if((_cargandoTodas)&&_totalCargados >= _cargadores.length)//Cuando se hayan cargado todas las fichas
			{
				colocarFichasEnMapa(mapaMatriz,_misFichas,deMapaXMLAArray(mapaActXML));
				_anchoFicha	=	redimencionarFichas(mapaMatriz[0].length,mapaMatriz[0][0].length,_misFichas,miMarco,MARGEN_IZQUIERDO,MARGEN_SUPERIOR);
				_altoFicha		=	_anchoFicha*1.5;
				ordenarFichas(mapaMatriz,_anchoFicha,_altoFicha,miMarco);
				activarFichas(mapaMatriz);
			}
		}
		private	function	deMapaXMLAArray(mX:XML):Array
		{
			var	res	:	Array	=	new	Array();
			var	i	:	uint;
			var	j	:	uint;
			var	k	:	uint;
			
			for(i=0;i<int(mX.@pisos);i++)
				for(j=0;j<int(mX.@filas);j++)
					for(k=0;k<int(mX.@columnas);k++)
						if(mX.piso[i].fila[j].charAt(k)=="1")
							res.push(new Punto3D(i,j,k));
			return	res;
		}
		public	function	colocarFichasEnMapa(mapa:Array,fichas:Array,posiciones:Array):void
		{
			/**
			Se colocan las fichas dentro del mapa, las posiciones son las posibles posiciones en las que se pueden colocar las fichas
			**/
			var	pos		:	uint;
			var	punto	:	Punto3D;
			var 	i			:	uint;
			var	auxFich	:	Array	=	new	Array();
			
			for(i=0;i<fichas.length;i++)
				auxFich.push(fichas[i]);
			for(i=0;i<fichas.length;i++)
			{
				pos		=	Math.floor((Math.random()*auxFich.length));
				punto	=	posiciones[i];
				mapa[punto.x][punto.y][punto.z]	=	auxFich[pos];
				auxFich.splice(pos,1);
			}
		}
		public	function	ordenarFichas(mapa:Array,anchoFicha:Number,altoFicha:Number,marco:DisplayObjectContainer):void
		/**
		Las fichas qiue estan en la matriz mapa, se visualizan, agregandolas al marco.
		**/
		{
			var mS	:	Number	=	(marco.height-(mapa[0].length*altoFicha))/1.5;//Margen superior
			var mI	:	Number	=	(marco.width-(mapa[0][0].length*anchoFicha))/2;//Margen Izquierdo
			for(var i:int=0;i<mapa.length;i++)
				for(var j:int=0;j<mapa[i].length;j++)
					for(var k:int=mapa[i][j].length-1;k>=0;k-=1)
						if((mapa[i][j][k]!=null)&&(mapa[i][j][k] is DisplayObject))
						{
							marco.addChild(mapa[i][j][k]);
							mapa[i][j][k].x	=	(k*(mapa[i][j][k].width-(mapa[i][j][k].margenIzquierdo)))+(i*mapa[i][j][k].margenIzquierdo)+mI;
							mapa[i][j][k].y	=	(j*(mapa[i][j][k].height-mapa[i][j][k].margenInferior))-(i*mapa[i][j][k].margenInferior)+mS;
						}
		}
		public	function	redimencionarFichas(filas:uint,columnas:uint,fichas:Array,marco:DisplayObject,margenIzq:Number,margenSup:Number):Number
		{
			/**
			Se verifica si el alto total del mapa es mayor que el ancho total, para redimencionar las fichas
			**/
			var	ancho	:	Number;
			var	alto		:	Number;
			if(filas*1.5>columnas)//Si es mas alto que ancho
			{
				alto		=	(marco.height-(margenSup))/filas;
				ancho	=	alto/1.5;
			}else//Si es mas ancho que alto
			{
				ancho	=	(marco.width-(margenIzq))/columnas;
				alto		=	ancho	*	1.5;
			}
			for(var	i:uint=0;i<fichas.length;i++)
			{
				(fichas[i] as Ficha).width	=	ancho;
				(fichas[i] as Ficha).height=	alto;
			}
			return	ancho;
		}
		private	function	posicionLibre(pos:Punto3D, mapa:Array):Boolean
		{
			var resultado : Boolean	=	false;
			var	libre:uint=0;
			if(pos.z==mapa.length-1)//Si esta en el ultimo piso
				libre++
			else if(mapa[pos.z+1][pos.x][pos.y]==null)//Si no está en el último piso, se verifica si la casilla del piso inmediatamente superior está vacía
				libre++;
			if((pos.y==0)||(pos.y==mapa[pos.z][pos.x].length-1))//Si esta al lado izquierdo o derecho
				libre++
			else if((mapa[pos.z][pos.x][pos.y-1]==null)||(mapa[pos.z][pos.x][pos.y+1]==null))//Si no está en ninguno de los extremos horizaontales, se verifica si alguno de sus lados está libre.
				libre++;
				
			return	libre>=2;
		}
		private	function	activarFichas(mapa:Array):void
		{
			for(var i:int=0;i<mapa.length;i++)
				for(var j:int=0;j<mapa[i].length;j++)
					for(var k:int=0;k<mapa[i][j].length;k++)
						if((mapa[i][j][k]!=null)&&(mapa[i][j][k] is DisplayObject))
							mapa[i][j][k].seleccionable=	posicionLibre(new Punto3D(j,k,i),mapa);
		}
		private	function	alClickFicha(e:MouseEvent):void
		{
			if((e.currentTarget as Ficha).seleccionable)
			{
				if(_fichaActual==	null)
				{
					_fichaActual	=	e.currentTarget as Ficha;
				}else
				{
					if((_fichaActual.valor == (e.currentTarget as Ficha).valor)&&(_fichaActual != e.currentTarget))
					{
						miMarco.removeChild(_fichaActual);
						miMarco.removeChild(e.currentTarget as Ficha );
						var aux:Array	=	Busquedas.buscarEnMatriz(_fichaActual,mapaMatriz);
						mapaMatriz[aux[0]][aux[1]][aux[2]]	=	null;
						aux	=	Busquedas.buscarEnMatriz(e.currentTarget as Ficha ,mapaMatriz);
						mapaMatriz[aux[0]][aux[1]][aux[2]]	=	null;
						activarFichas(mapaMatriz);
					}else
					{
						_fichaActual.deseleccionar();
						(e.currentTarget as Ficha ).deseleccionar();
					}
					_fichaActual	=	null;
				}
			}
		}
	}
}